﻿using Aribaccio;
using BDPAutodetect.DataService;
using BDPAutodetect.Device;
using BDPAutodetect.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection.Metadata;
using System.Text;
using System.Threading.Tasks;

namespace BDPAutodetect.Mgrcore
{
    /// <summary>
    /// 角色权限管理
    /// </summary>
    public partial class RolePowerManager : BaseManager
    {
        /// <summary>
        /// 基础数据操作对象
        /// </summary>
        protected IDataServiceBasic DataService { get; set; }
        /// <summary>
        /// 角色集合
        /// </summary>
        public List<MRoleDto> Roles { get; protected set; }
        /// <summary>
        /// 权限集合
        /// </summary>
        public List<MPowerDto> Powers { get; protected set; }
        /// <summary>
        /// 角色权限集合
        /// </summary>
        public List<MRolePower> RolePowers { get; protected set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        public RolePowerManager(IDataServiceBasic argDataService)
            : base("角色权限管理中心")
        {
            this.DataService = argDataService;
            this.Roles = new List<MRoleDto>();
            this.Powers = new List<MPowerDto>();
            this.RolePowers = new List<MRolePower>();
        }

        /// <summary>
        /// 初始化
        /// </summary>
        public override async Task Initialize()
        {
            //获取数据库-角色数据
            await this.InitializeRoles();
            //获取数据库-权限数据
            await this.InitializePowers();
            //获取角色权限关系表数据，创建角色权限集合
            await this.InitializeRPRelation();
        }

        /// <summary>
        /// 初始化角色数据
        /// </summary>
        /// <returns></returns>
        protected async Task InitializeRoles()
        {
            var results = this.DataService.SelectModelItemsTask<TBasicRole>();
            await results.ConfigureAwait(false);

            if (results == null
                || results.Result == null || !results.Result.ResultState
                || results.Result.Data == null || results.Result.Data.Count <= 0) return;

            foreach (var item in results.Result.Data)
            {
                this.Roles.Add(new MRoleDto(item.ID, item.Name, item.Supered));
            }
        }

        /// <summary>
        /// 初始化权限数据
        /// </summary>
        /// <returns></returns>
        protected async Task InitializePowers()
        {
            var results = this.DataService.SelectModelItemsTask<TBasicPower>();
            await results.ConfigureAwait(false);

            if (results == null
              || results.Result == null || !results.Result.ResultState
              || results.Result.Data == null || results.Result.Data.Count <= 0) return;

            foreach (var item in results.Result.Data)
            {
                this.Powers.Add(new MPowerDto(item.ID, item.Name)
                {
                    ParentID = item.ParentID,
                    MenuStatus = item.MenuStatus,
                    TreeStatus = item.TreeStatus,
                    Url = item.Url,
                    Inco = item.Inco
                });
            }
        }

        /// <summary>
        /// 初始化角色权限数据
        /// </summary>
        /// <returns></returns>
        protected async Task InitializeRPRelation()
        {
            //获取角色权限关系表数据
            var results = this.DataService.SelectModelItemsTask<TBasicRPRelation>();
            await results.ConfigureAwait(false);

            if (results == null
             || results.Result == null || !results.Result.ResultState
             || results.Result.Data == null || results.Result.Data.Count <= 0) return;

            List<TBasicRPRelation> rpRelations = results.Result.Data;
            //循环创建角色权限集合
            foreach (var roleItem in this.Roles)
            {
                var rPowers = rpRelations.Where(v => v.RoleID == roleItem.ID);
                if (rPowers == null || rPowers.Count() <= 0) continue;

                MRolePower rolePower = new MRolePower(roleItem);
                foreach (var rPower in rPowers)
                {
                    var power = this.Powers.First(v => v.ID == rPower.PowerID);
                    if (power == null) continue;
                    rolePower.AddPower(new MPowerPermission(rPower.ID, roleItem, power, rPower.Permission));
                }
                this.RolePowers.Add(rolePower);
            }
        }

        /// <summary>
        /// 新增角色
        /// </summary>
        /// <param name="argRoleName">角色名称</param>
        /// <returns></returns>
        public async Task<MRoleDto?> InsertRole(MRoleDto argRole)
        {
            if (argRole == null) return null;
            TBasicRole basicRole = argRole.CloneTData();
            if (this.CheckExsits(basicRole)) return null;

            var result = this.DataService.InsertTask(basicRole);
            await result.ConfigureAwait(false);
            if (result != null && result.Result != null && result.Result.ResultState)
            {
                var newRole = this.DataService.SelectModelItem<TBasicRole>(v => v.Name == basicRole.Name);
                if (newRole == null || !newRole.ResultState || newRole.Data == null)
                {
                    var resultDelete = this.DataService.DeleteWhereTask<TBasicRole>(v => v.Name == basicRole.Name);
                    await resultDelete.ConfigureAwait(false);
                    return default;
                }

                bool bIsOk = true;
                MRoleDto roleData = new MRoleDto(newRole.Data.ID, newRole.Data.Name, newRole.Data.Supered);
                MRolePower rolePower = new MRolePower(roleData);
                foreach (var powerItem in this.Powers.OrderBy(v => v.ID))
                {
                    MPowerPermission? newPowerPermission = this.InsertRolePower(new MPowerPermission(0, roleData, powerItem, 0));
                    if (newPowerPermission == null)
                    {
                        bIsOk = false;
                        break;
                    }
                    rolePower.Powers.Add(newPowerPermission);
                }
                if (bIsOk)
                {
                    this.RolePowers.Add(rolePower);
                    return roleData;
                }
                else
                {
                    var deleteTask = this.DataService.DeleteWhereTask<TBasicRole>(v => v.ID == roleData.ID);
                    await deleteTask.ConfigureAwait(false);
                    deleteTask = this.DataService.DeleteWhereTask<TBasicRPRelation>(v => v.RoleID == roleData.ID);
                    await deleteTask.ConfigureAwait(false);
                    return default;
                }
            }
            return default;
        }

        public async Task<bool> DeleteRole(MRoleDto argRole)
        {
            if (argRole == null) return false;
            var result = this.DataService.DeleteWhereTask<TBasicRole>(v => v.ID == argRole.ID);
            await result.ConfigureAwait(false);
            if (result != null && result.Result.ResultState)
            {
                //删除角色权限
                var resultRPRelation = this.DataService.DeleteWhereTask<TBasicRPRelation>(v => v.RoleID == argRole.ID);
                await resultRPRelation.ConfigureAwait(false);
                //移除缓存
                var removeRole = this.Roles.First(v => v.ID == argRole.ID);
                var removeRolePower = this.RolePowers.First(v => v.Role.ID == removeRole.ID);
                this.RolePowers.Remove(removeRolePower);
                this.Roles.Remove(removeRole);
                return true;
            }
            else { return false; }
        }

        /// <summary>
        /// 更新角色
        /// </summary>
        /// <param name="argRole"></param>
        /// <returns></returns>
        public async Task<bool> UpdateRole(MRoleDto argRole)
        {
            if (argRole == null) return false;
            TBasicRole basicRole = argRole.CloneTData();
            if (this.CheckExsits(basicRole)) return false;

            var result = this.DataService.UpdateWhereTask<TBasicRole>(basicRole, v => v.ID == basicRole.ID);
            await result.ConfigureAwait(false);
            if (result == null || result.Result == null || !result.Result.ResultState) return false;

            var role = this.Roles.First(v => v.ID == argRole.ID);
            if (role != null)
            {
                role.Name = argRole.Name;
            }
            return true;
        }

        /// <summary>
        /// 新增角色权限关系
        /// </summary>
        /// <param name="argPowerPermission"></param>
        /// <returns></returns>
        public MPowerPermission? InsertRolePower(MPowerPermission argPowerPermission)
        {
            if (argPowerPermission == null || argPowerPermission.Power == null) return null;
            var result = this.DataService.Insert<TBasicRPRelation>(argPowerPermission.CloneTData());
            if (result == null || !result.ResultState) return null;

            var newPowerPermission = this.DataService.SelectModelItem<TBasicRPRelation>(v => v.RoleID == argPowerPermission.Role.ID && v.PowerID == argPowerPermission.Power.ID);
            if (newPowerPermission == null || !newPowerPermission.ResultState || newPowerPermission.Data == null)
            {
                return default;
            }
            argPowerPermission.ID = newPowerPermission.Data.ID;
            return argPowerPermission;
        }

        /// <summary>
        /// 更新角色权限关系
        /// </summary>
        /// <param name="argTreeNodes"></param>
        /// <returns></returns>
        public async Task<bool> UpdateRolePower(List<TreeNode<MPowerPermission>> argTreeNodes)
        {
            var powerPermissions = this.GetBasicRPRelations(argTreeNodes);
            bool bPass = true;
            foreach (var item in powerPermissions)
            {
                var rpRelation = item.Key.CloneTData();
                rpRelation.Permission = item.Value == ExecuteStatus.Yes ? 1 : 0;
                var result = this.DataService.UpdateWhereTask<TBasicRPRelation>(rpRelation, v => v.ID == rpRelation.ID);
                await result.ConfigureAwait(false);
                if (result == null || result.Result == null || !result.Result.ResultState)
                {
                    bPass = false;
                }
                else
                {
                    item.Key.Permission = rpRelation.Permission;
                }
            }
            return bPass;
        }

        /// <summary>
        /// 检测名称是否存在
        /// </summary>
        /// <param name="argRole"></param>
        /// <returns></returns>
        public bool CheckExsits(TBasicRole argRole)
        {
            Result check = argRole.ID > 0
                ? this.DataService.Exsits<TBasicRole>(v => v.ID != argRole.ID && v.Name.Equals(argRole.Name, StringComparison.OrdinalIgnoreCase))
                : this.DataService.Exsits<TBasicRole>(v => v.Name.Equals(argRole.Name, StringComparison.OrdinalIgnoreCase));
            return (check != null && check.ResultState);
        }


        /// <summary>
        /// 获取角色
        /// </summary>
        /// <param name="argRoleID">角色ID</param>
        /// <returns></returns>
        public MRoleDto? GetRole(int argRoleID)
        {
            if (this.Roles.Count <= 0) return null;
            return this.Roles.FirstOrDefault(v => v.ID == argRoleID);
        }

        /// <summary>
        /// 获取角色集合
        /// </summary>
        public List<MRoleDto> GetRoles(bool IsSupered = false)
        {
            if (IsSupered) return this.Roles;
            var roles = this.Roles.Where(v => v.Supered == 0);
            return roles != null ? roles.ToList() : new List<MRoleDto>();
        }

        /// <summary>
        /// 获取权限列表
        /// </summary>
        /// <param name="argRoleID">角色ID</param>
        /// <param name="argParentID">父级权限ID，默认0表示顶层</param>
        /// <returns></returns>
        public List<MPowerPermission>? GetPowers(int argRoleID, int argParentID = 0)
        {
            if (argRoleID <= 0 || this.RolePowers.Count <= 0) return null;

            var rolePower = RolePowers.FirstOrDefault(v => v.Role.ID == argRoleID);
            if (rolePower == null) return null;

            var rPowers = rolePower.Powers.Where(v => v.PermissionMode == ExecuteStatus.Yes && v.Power.ParentID == argParentID);
            return rPowers != null ? rPowers.ToList() : null;
        }

        /// <summary>
        /// 获取权限菜单
        /// </summary>
        /// <param name="argRoleID">角色ID</param>
        /// <param name="argParentID">父级权限ID，默认0表示主菜单</param>
        /// <returns></returns>
        public List<MPowerMenu> GetPowerMenus(int argRoleID, int argParentID = 0)
        {
            List<MPowerMenu> resultMenus = new List<MPowerMenu>();
            var rPowers = this.GetPowers(argRoleID, argParentID);
            if (rPowers == null || rPowers.Count <= 0) return resultMenus;

            foreach (var item in rPowers)
            {
                resultMenus.Add(new MPowerMenu(item));
            }
            return resultMenus;
        }

        /// <summary>
        /// 获取树形节点
        /// </summary>
        /// <param name="argRoleID">角色ID</param>
        /// <param name="argIsEnabled">是否可有效选择</param>
        /// <param name="argIsExpanded">是否默认展开</param>
        /// <returns></returns>
        public List<TreeNode<MPowerPermission>> GetPowerTrees(int argRoleID, bool argIsEnabled = false, bool argIsExpanded = false)
        {
            var resultTrees = new List<TreeNode<MPowerPermission>>();
            if (argRoleID <= 0 || this.RolePowers.Count <= 0) return resultTrees;

            var rolePower = this.RolePowers.FirstOrDefault(v => v.Role.ID == argRoleID);
            if (rolePower == null) return resultTrees;

            return this.GetRecursionPowerTrees(rolePower.Powers, null, argIsEnabled, argIsExpanded);
        }

        /// <summary>
        /// 获取树形节点[递归]
        /// </summary>
        /// <param name="argPowers">所有权限列表</param>
        /// <param name="argParent">父级节点，空表示第一层级</param>
        /// <param name="argIsEnabled">是否可有效选择</param>
        /// <param name="argIsExpanded">是否默认展开</param>
        /// <returns></returns>
        protected List<TreeNode<MPowerPermission>> GetRecursionPowerTrees(List<MPowerPermission> argPowers, TreeNode<MPowerPermission>? argParent, bool argIsEnabled = false, bool argIsExpanded = false)
        {
            var resultTrees = new List<TreeNode<MPowerPermission>>();
            //获取子权限
            int nParentID = argParent?.ID ?? 0;
            var powerChilds = argPowers.Where(v => v.Power.ParentID == nParentID);
            if (powerChilds == null || powerChilds.Count() <= 0) return resultTrees;
            //循环添加树形节点
            foreach (var item in powerChilds.OrderBy(v => v.Power.ID))
            {
                bool bIsChecked = item.PermissionMode == ExecuteStatus.Yes;
                TreeNode<MPowerPermission> treeNode = new TreeNode<MPowerPermission>(item.Power.ID, item.Power.Name, item, bIsChecked, argIsEnabled, argIsExpanded, argParent);
                //递归添加子节点
                var treeChilds = this.GetRecursionPowerTrees(argPowers, treeNode, argIsEnabled, argIsExpanded);
                if (treeChilds != null && treeChilds.Count > 0)
                {
                    treeNode.AddChilds(treeChilds);
                }
                resultTrees.Add(treeNode);
            }
            return resultTrees;
        }

        /// <summary>
        /// 获取权限许可集合[递归]
        /// </summary>
        /// <param name="argTreeNodes">树形节点</param>
        /// <returns></returns>
        protected Dictionary<MPowerPermission, ExecuteStatus> GetBasicRPRelations(List<TreeNode<MPowerPermission>> argTreeNodes)
        {
            Dictionary<MPowerPermission, ExecuteStatus> resultPowers = new Dictionary<MPowerPermission, ExecuteStatus>();
            foreach (var item in argTreeNodes)
            {
                resultPowers.Add(item.SourceData, item.IsChecked ? ExecuteStatus.Yes : ExecuteStatus.No);
                if (item.IsExistsChilds && item.Childs != null)
                {
                    //递归获取字节点权限许可
                    var resultPowerChilds = this.GetBasicRPRelations(item.Childs.ToList());
                    if (resultPowerChilds != null && resultPowerChilds.Count > 0)
                    {
                        foreach (var itemChild in resultPowerChilds)
                        {
                            resultPowers.Add(itemChild.Key, itemChild.Value);
                        }
                    }
                }
            }
            return resultPowers;
        }
    }
}
